// ...........................................................................................................
// (C) Copyright  1996/2008 Fuego Inc.  All Rights Reserved
// THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF Fuego Inc.
// The copyright notice above does not evidence any actual or intended
// publication of such source code.
//
// Last changed on 2008-03-10 19:12:16 (-0300), by: machaval. $Revision$
// ...........................................................................................................

package com.webcamtracker.color.segmentation;

import com.webcamtracker.tracker.TrackHistory;

public class SearchWindowProviderImpl
        implements SearchWindowProvider {
    private static final int WINDOW_DELTA = 16;
    private static final int MAX_HISTORYSIZE = 4;
    //~ Methods ..............................................................................................

    public SearchWindow getSearchWindow(TrackHistory<TrackingObject> history, int imageWidth, int imageHeight, long timeNow) {

        final int size = history.size();
        SearchWindow candidate = null;

        switch (size) {
            case 0:
                System.out.println("El Tamano del histograma es cero!!!");
                break;
            case 2:
            case 1:
                candidate = buildWindowFromTrackingObject(history.peek(), imageWidth, imageHeight);
                break;
            default:

                TrackHistory.TrackerHistoryElement<TrackingObject> previous = null;
                long xVelocity = 0;
                long yVelocity = 0;
                long totalWeight = 0;
                int i = 0;
                for (TrackHistory.TrackerHistoryElement<TrackingObject> element : history) {
                    if (previous != null && i <= MAX_HISTORYSIZE) {
                        final TrackingObject previousModel = previous.getModel();
                        final TrackingObject elementModel = element.getModel();

                        final long deltaT = element.getTime() - previous.getTime();

                        final int xDistance = previousModel.getX() - elementModel.getX();
                        final int yDistance = previousModel.getY() - elementModel.getY();

                        final int weight = history.size() - i;
                        xVelocity += (xDistance * weight) / deltaT;
                        yVelocity += yDistance / deltaT;
                        totalWeight += weight;
                    }

                    i++;
                    previous = element;
                }

                xVelocity = xVelocity /totalWeight;
                yVelocity = yVelocity / totalWeight;

                final TrackHistory.TrackerHistoryElement<TrackingObject> last = history.get(0);
                final long spentTime = timeNow - last.getTime();
                final int deltaX = (int) (xVelocity * spentTime);
                final int deltaY = (int) (yVelocity * spentTime);
                final TrackingObject lastObject = last.getModel();
                final int newX = lastObject.getX() + deltaX - (WINDOW_DELTA / 2);
                final int newY = lastObject.getY() + deltaY - (WINDOW_DELTA / 2);

                final int width = lastObject.getWidth() + WINDOW_DELTA;
                final int height = lastObject.getHeight() + WINDOW_DELTA;

                if (checkBoundries(newX, newY, width, height, imageWidth, imageHeight)) {
                    candidate = new SearchWindow(newX, newY, width, height);
                } else {
                    candidate = buildWindowFromTrackingObject(history.peek(), imageWidth, imageHeight);
                }

                break;
        }

        return candidate;
    }

    private SearchWindow buildWindowFromTrackingObject(TrackingObject object, int maxX, int maxY) {

        final int delta = WINDOW_DELTA;
        final int shift = delta / 2;
        int x = object.getX() - shift;
        if (x < 0) {
            x = 0;
        }
        int y = object.getY() - shift;
        if (y < 0) {
            y = 0;
        }
        int width = object.getWidth() + delta;
        int height = object.getHeight() + delta;
        if (x + width > maxX) {
            width = maxX - x;
        }

        if (y + height > maxY) {
            height = maxY - y;
        }


        return new SearchWindow(x, y, width, height);

    }

    private boolean checkBoundries(int newX, int newY, int width, int height, int imageWidth, int imageHeight) {
        boolean ok;
        ok = newX > 0 && newY > 0;
        ok = ok && newX + width < imageWidth;
        ok = ok && newY + height < imageHeight;
        return ok;
    }
}
